/*
 *  uaeexe.c - UAE remote cli
 *
 *  (c) 1997 by Samuel Devulder
 */

#include "sysconfig.h"
#include "uaeexe.h"
#include "thread.h"
#include "newcpu.h"
#include "traps.h"
#include "filesys.h"
#include "hardfile.h"

static struct uae_xcmd* first = nullptr;
static struct uae_xcmd* last = nullptr;
static TCHAR running = 0;
static uint REGPARAM3 uaeexe_server(TrapContext* context) REGPARAM;

/*
 * Install the server
 */
void uaeexe_install()
{
    uae_ptr loop;

    loop = here();
    org(UAEEXE_ORG);
    calltrap(deftrapres(uaeexe_server, 0, L"uaeexe_server"));
    dw(RTS);
    org(loop);
}

/*
 * Send command to the remote cli.
 *
 * To use this, just call uaeexe("command") and the command will be
 * executed by the remote cli (provided you've started it in the
 * s:user-startup for example). Be sure to add "run" if you want
 * to launch the command asynchronously. Please note also that the
 * remote cli works better if you've got the fifo-handler installed.
 */
int uaeexe(const TCHAR* cmd)
{
    struct uae_xcmd* nw;

    if (!running)
        goto NORUN;

    nw = xmalloc(struct uae_xcmd, 1);
    if (!nw)
        goto NOMEM;
    nw->cmd = xmalloc(TCHAR, _tcslen(cmd) + 1);
    if (!nw->cmd)
    {
        free(nw);
        goto NOMEM;
    }

    _tcscpy(nw->cmd, cmd);
    nw->prev = last;
    nw->next = nullptr;

    if (!first)
        first = nw;
    if (last)
    {
        last->next = nw;
        last = nw;
    }
    else
        last = nw;

    return UAEEXE_OK;
NOMEM:
    return UAEEXE_NOMEM;
NORUN:
    Logger::Write(L"Remote cli is not running.\n");
    return UAEEXE_NOTRUNNING;
}

/*
 * returns next command to be executed
 */
static TCHAR* get_cmd()
{
    struct uae_xcmd* cmd;
    TCHAR* s;

    if (!first)
        return nullptr;
    s = first->cmd;
    cmd = first;
    first = first->next;
    if (!first)
        last = nullptr;
    free(cmd);
    return s;
}

/*
 * helper function
 */
#define ARG(x) (get_long(m68k_areg(regs, 7) + 4 * (x + 1)))
static uint REGPARAM2 uaeexe_server(TrapContext* context)
{
    int len;
    TCHAR* cmd;
    char* dst, * s;

    if (ARG(0) && !running)
    {
        running = 1;
        Logger::Write(L"Remote CLI started.\n");
    }

    cmd = get_cmd();
    if (!cmd)
        return 0;
    if (!ARG(0))
    {
        running = 0;
        return 0;
    }

    dst = (char*)get_real_address(ARG(0));
    len = ARG(1);
    s = Unicode::ua(cmd);
    strncpy(dst, s, len);
    Logger::Write(L"Sending '%s' to remote cli\n", cmd);
    free(s);
    free(cmd);
    return ARG(0);
}